<!doctype html>
<html>
<head>
<meta charset="utf-8">
<title>test</title>
<script>



//【示例1】下面示例演示了一个更复杂的多重继承的实例。
// 基类A
function A( x ){ 	// 构造函数A
    this.getl = function(){	// 本地方法，获取参数值
        return x;
    }
}
A.prototype.has = function(){	// 原型方法，判断getl()方法返回值是否为0（false）
    return ! ( this.getl() == 0 );
}
// 超类B
function B(){	// 构造函数B
    var a = [];	// 私有数组a
    a = Array.apply( a, arguments ); 	// 把参数数组传入数组a中
    A.call( this, a.length ); 	// 在当前对象中调用A类，并把参数数组长度传递给它
    this.add = function(){	// 本地方法，把参数数组补加到数组a中，并返回
        return a.push.apply( a, arguments ); 
    }
    this.geta = function(){	// 本地方法，返回数组a
        return a; 
    }
}
B.prototype = new A();	// 设置B类的原型为A类的实例，从而建立原型链
B.prototype.constructor = B; 	// 恢复B类原型对象的构造器
B.prototype.str = function(){	// 原型方法，把数组转换为字符串并返回
    return this.geta().toString();
}
// 子类C
function C(){	// 构造函数
    B.apply( this, arguments ); 	// 在当前对象中调用B类，并把参数数组长度传递给它
    this.sort = function(){	// 本地方法，以字符顺序对数组进行排序
        var a = this.geta();	// 获取数组的值
        a.sort.apply( a, arguments ); 
	// 调用数组排序方法sort()对数组进行排序
    }
}
C.prototype = new B();	// 设置C类的原型为B类的实例，从而建立原型链
C.prototype.constructor = C; 	// 恢复C类原型对象的构造器
// 超类B的实例继承类A的成员
var b  = new B( 1, 2, 3, 4 ); 	// 实例化B类
alert( b.getl() ); 	// 返回4，调用A类的方法getl()
alert( b.has() ); 	// 返回true，调用A类的方法has()
// 子类C的实例继承类B和类A的成员
var c  = new C( 30, 10, 20, 40 ); 	// 实例化C类
c.add( 6, 5 ); 	// 调用B类方法add()，补加数组
alert( c.geta() ) 	// 返回数组30,10 ,20,40 ,6,5
c.sort()	// 排序数组
alert( c.geta() ) 	// 返回数组10,20 ,30,40 ,5,6
alert( c.getl() ) 	// 返回4，调用A类的方法getl()
alert( c.has() ); 	// 返回true，调用A类的方法has()
alert( c.str() ); 	// 返回10,20 ,30,40 ,5,6
//【示例2】下下面尝试把类继承模式封装起来，以便规范代码应用。
//第1步，定义一个封装函数。设计入口为子类和超类对象，函数功能是子类能够继承超类的所有原型成员，不设计出口。
function extend(Sub,Sup){ 			// 类继承封装函数
    // 其中参数Sub表示子类，Sup表示超类
}
///第2步，恢复子类原型的构造器子类自己。同时，检测超类原型构造器是否与Object的原型构造器发生耦合，如果是，则恢复它的构造器为超类自身。
function extend(Sub,Sup){ 	// 类继承封装函数
    var F = function(){};	// 定义一个空函数
    F.prototype = Sup.prototype; 	// 设置空函数的原型为超类的原型
    Sub.prototype = new F();	// 实例化空函数，并把超类原型引用传递给子类
    Sub.prototype.constructor = Sub;	// 恢复子类原型的构造器为子类自身
    Sub.sup = Sup.prototype; 	// 在子类定义一个本地属性存储超类原型
    if(Sup.prototype.constructor == Object.prototype.constructor){ 	//检测超类原型构造器是否为自身
        Sup.prototype.constructor =Sup	// 类继承封装函数
    }
}
//第3步，一个简单的功能封装函数就这样实现了。下面定义两个类，尝试把它们绑定为继承关系。
function A(x){ 	// 构造函数A
    this.x = x; 	// 本地属性x
    this.get = function(){	// 本地方法get()
        return this.x;
    }
}
A.prototype.add = function(){	// 原型方法add()
    return this.x + this.x;
} 
A.prototype.mul = function(){	// 原型方法mul()
    return this.x * this.x;
}
function B(x){ 	// 构造函数B
    A.call(this,x); 	// 在函数体内调用构造函数A，实现内部数据绑定
}
extend(B,A); 	// 调用类继承封装函数，把A和B的原型捆绑在一起
var f = new B(5); 	// 实例化类B
alert(f.get())	// 继承类A的方法get()，返回5
alert(f.add())	// 继承类A的方法add()，返回10
alert(f.mul())	// 继承类A的方法mul()，返回25
//第4步，在继承类封装函数中，有这么一句Sub.sup = Sup.prototype;，在上面的代码中没有被利用，那么它有什么作用呢？为了解答这个问题，先看下面的代码：
extend(B,A);
B.prototype.add = function(){	// 为B类定义一个原型方法
    return this.x + "" + this.x
}

alert(f.add())	// 返回字符串55，而不是数值10
//第5步，如果在B类的原型方法add()中调用超类的原型方法add()，从而避免代码耦合现象发生：
B.prototype.add = function(){	// 定义子类B的原型方法add()
    return B.sup.add.call(this); 	// 在函数内部调用超类方法add()
}





</script>
</head>
<body>
</body>
</html>
